package com.wutong.eams.controller;

import com.wutong.eams.bean.ErrorMessage;
import com.wutong.eams.entity.User;
import com.wutong.eams.enums.RequestMethod;
import com.wutong.eams.enums.Role;
import com.wutong.eams.exception.UserOperationException;
import com.wutong.eams.interfaces.Permission;
import com.wutong.eams.other.JsonMap;
import com.wutong.eams.other.Router;
import com.wutong.eams.service.StudentManagerService;
import com.wutong.eams.service.UserAuthenticService;
import com.wutong.eams.service.UserManagerService;
import com.wutong.eams.utils.ObjectUtil;
import com.wutong.eams.utils.RouterUtil;
import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
public abstract class BaseController extends HttpServlet implements Permission {

    @Getter
    private final UserAuthenticService userAuthenticService = new UserAuthenticService();
    @Getter
    private final UserManagerService userManagerService = new UserManagerService();
    @Getter
    private final StudentManagerService studentManagerService = new StudentManagerService();

    protected final String CONTENT_TYPE_TEXT_HTML = "text/html;charset=UTF-8";
    protected final String CONTENT_TYPE_APPLICATION_JSON = "application/json;charset=UTF-8";
    protected final String CONTENT_TYPE_TEXT_PLAIN = "text/plain;charset=UTF-8";

    @Getter
    private final Router router = Router.of();

    protected void addRouter(String originUrl, Router.RouteAttribute routeAttribute) {
        router.add(originUrl, routeAttribute);
    }

    protected void initRouter() {
        router.add("/students", RequestMethod.GET, "text/html;charset=UTF-8", "/page/students");
    }

    protected void routerHandle() {
//        throw new UnsupportedOperationException("请在子类中实现该方法");
    }

    @Override
    public void init(ServletConfig config) throws ServletException {
        initRouter();
        super.init(config);
    }

    protected void setJsonReturn(HttpServletResponse response) {
        response.setContentType("application/json;charset=UTF-8");
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with, authorization, content-type");
    }

    protected void sendResponseByJson(JsonMap jsonMap, HttpServletResponse response) throws IOException {
        setJsonReturn(response);
        response.getWriter().write(jsonMap.buildToJson());
    }

    protected void viewForward(String viewRule, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String header = "/WEB-INF/views";
        if (!viewRule.startsWith("/")) {
            header += "/";
        }
        log.info("JSP路由跳转至: {}", viewRule);
        request.getRequestDispatcher(header + viewRule).forward(request, response);
    }

    protected void routerRedirect(String routerRule, HttpServletRequest request, HttpServletResponse response) {
        log.info("JSP路由重定向至: {}", routerRule);
        try {
            response.sendRedirect(request.getContextPath() + routerRule);
        } catch (IOException e) {
            log.error("路由跳转失败", e);
        }
    }

    protected boolean hasCurrentRule(String targetRule, HttpServletRequest request, HttpServletResponse response) {
        if (!targetRule.startsWith("/")) {
            targetRule = "/" + targetRule;
        }
        if (!request.getRequestURI().endsWith(targetRule)) {
            response.setStatus(404);
            log.warn("请求路径: {} 不存在", request.getRequestURI());
            return false;
        }
        return true;
    }

    protected User getSessionUser(HttpServletRequest request) {
        return (User) request.getSession().getAttribute("user");
    }

    private boolean perssionLoding(HttpServletRequest request) {
        if (!needPermission()) {
            return true;
        }
        if (RouterUtil.isWhiteListed(request.getRequestURI(), getWhiteList())) {
            return true;
        }
        return Role.getByName(getSessionUser(request).getRole()).getRoleValue() >= getPermission().getRoleValue();
    }

    private void debugInfo() {
        router.printAllRoutes();
    }

    protected void initLoad(HttpServletRequest req, HttpServletResponse resp) {
        if (!perssionLoding(req)) {
            throw new UserOperationException.UserPermissionException("用户权限不足");
        }
        ErrorMessage errorMessage = new ErrorMessage(null);
        req.setAttribute("errorMessage", errorMessage);
        if (log.isDebugEnabled()) {
            debugInfo();
        }
        routerHandle();
    }

    public <T> T parseJsonRequest(HttpServletRequest req, Class<T> clazz) {
        try {
            return ObjectUtil.convertJsonToEntity(req.getReader().readLine(), clazz);
        } catch (IOException e) {
            log.error("解析请求参数失败", e);
            return null;
        }
    }

    /**
     * 发送JSON格式响应
     * @param response HttpServletResponse对象
     * @param status HTTP状态码
     * @param data 要返回的数据对象
     * @throws IOException 异常
     */
    public static void sendJsonResponse(HttpServletResponse response, int status, Object data) throws IOException {
        // 设置响应头
        response.setContentType("application/json");
        response.setCharacterEncoding("UTF-8");
        response.setStatus(status);

        // 构建响应体
        Map<String, Object> responseBody = new HashMap<>();
        responseBody.put("code", status);
        responseBody.put("data", data);
        responseBody.put("timestamp", System.currentTimeMillis());

        // 写入响应
        try (PrintWriter writer = response.getWriter()) {
            writer.write(ObjectUtil.toJson(responseBody));
            writer.flush();
        }
    }

    /**
     * 发送错误响应
     * @param response HttpServletResponse对象
     * @param status HTTP状态码
     * @param message 错误信息
     * @throws IOException 异常
     */
    public static void sendErrorResponse(HttpServletResponse response, int status, String message) throws IOException {
        response.setContentType("application/json");
        response.setCharacterEncoding("UTF-8");
        response.setStatus(status);

        Map<String, Object> errorResponse = new HashMap<>();
        errorResponse.put("code", status);
        errorResponse.put("message", message);
        errorResponse.put("timestamp", System.currentTimeMillis());

        try (PrintWriter writer = response.getWriter()) {
            writer.write(ObjectUtil.toJson(errorResponse));
            writer.flush();
        }
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        log.debug("{} - Function: doGet", getClass().getSimpleName());
        initLoad(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        log.debug("{} - Function: doPost", getClass().getSimpleName());
        initLoad(req, resp);
    }

    @Override
    protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        log.debug("{} - Function: doPut", getClass().getSimpleName());
        initLoad(req, resp);
    }

    @Override
    protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        log.debug("{} - Function: doDelete", getClass().getSimpleName());
        initLoad(req, resp);
    }
}

